/**
 * Alibaba.com.cn Inc.
 * Copyright (c) 2004-2021 All Rights Reserved.
 */
package com.starlink.common.strategy.deposit;

import com.starlink.common.enums.OrderTypeEnum;
import com.starlink.common.strategy.IPayNotify;
import com.starlink.mapper.DepositRecordMapper;
import com.starlink.model.domain.DepositRecordDO;
import com.starlink.model.dtomapper.DepositRecordDtoMapper;
import com.starlink.model.request.DepositRecordRequest;
import com.starlink.model.request.mall.WechatPay;
import com.starlink.model.request.mall.WechatRefund;
import com.starlink.service.*;
import com.starlink.utils.IRedisCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.starlink.common.enums.DepositOpTypeEnum.DEPOSIT_ADD;
import static com.starlink.common.enums.DepositOpTypeEnum.DEPOSIT_SUB;
import static com.starlink.common.enums.DepositTitleEnum.CASH;
import static com.starlink.common.enums.DepositTitleEnum.DEPOSIT_CHARGE;
import static com.starlink.common.enums.RedisHashKeyEnum.DEPOSIT_REFUND;
import static com.starlink.common.enums.RedisHashKeyEnum.ORDER_REFUND;

/**
 * @author zhanghong
 * @version BookPayNotify.java, v 0.1 2024/4/11 23:02 下午 BookPayNotify Exp $$
 */
@Component
public class DepositNotify implements IPayNotify {
    @Autowired
    private DepositRecordService depositRecordService;
    @Autowired
    private DepositRecordMapper depositRecordMapper;
    @Autowired
    private IRedisCacheService redisCacheService;

    private static final long EXPIRE_SECONDS = 60 * 60; // 过期时间，单位：秒

    @Override
    public boolean supports(Integer orderType) {
        return orderType.equals(OrderTypeEnum.DEPOSIT.getType());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handle(WechatPay wechatPay) {
        String weChatOrderId = wechatPay.getWeChatOrderId();
        String orderNum = wechatPay.getOrderNum();
        Long userId = wechatPay.getUserId();
        BigDecimal payAmount = new BigDecimal(wechatPay.getAmount());
        DepositRecordRequest request = new DepositRecordRequest();
        request.setUserId(userId);
        request.setTitle(DEPOSIT_CHARGE.getType());
        request.setChangeCashPledge(payAmount);
        request.setOrderNum(orderNum);
        request.setPayId(weChatOrderId);
        request.setOperationType(DEPOSIT_ADD.getType());
        DepositRecordDO recordDO = depositRecordService.lambdaQuery()
                .eq(DepositRecordDO::getUserId, userId)
                .orderByDesc(DepositRecordDO::getCreateTime)
                .last("LIMIT 1")
                .one();
        if (recordDO != null){
            BigDecimal balanceCashPledge = recordDO.getBalanceCashPledge();
            request.setBalanceCashPledge(balanceCashPledge.add(payAmount));
        }else {
            request.setBalanceCashPledge(payAmount);
        }
        depositRecordService.add(request);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refundHandle(WechatRefund wechatPay) {
        Long userId = wechatPay.getUserId();
        Boolean has = redisCacheService.hashGet(DEPOSIT_REFUND.name(), userId.toString());
        if (has == null) {
            DepositRecordRequest recordRequest = new DepositRecordRequest();
            recordRequest.setUserId(userId);
            recordRequest.setTitle(CASH.getType());
            recordRequest.setChangeCashPledge(wechatPay.getBalance());
            recordRequest.setOperationType(DEPOSIT_SUB.getType());
            recordRequest.setCreateTime(new Date());
            recordRequest.setBalanceCashPledge(BigDecimal.ZERO);
            recordRequest.setPayId(wechatPay.getWxRefundNum());
            depositRecordMapper.insertDO(DepositRecordDtoMapper.INSTANCE.request2DO(recordRequest));
            redisCacheService.hashPushHashMap(DEPOSIT_REFUND.name(), userId.toString(), true, EXPIRE_SECONDS, TimeUnit.SECONDS);
        }
    }
}
